package com.deer.wms.inventory.service.impl;

import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.deer.wms.base.system.service.CellInfoService;
import com.deer.wms.inventory.constant.InventoryConstant;
import com.deer.wms.inventory.dao.InventoryMapper;
import com.deer.wms.inventory.dao.InventoryTransactMapper;
import com.deer.wms.inventory.model.Inventory.Inventory;
import com.deer.wms.inventory.model.Inventory.InventoryTransact;
import com.deer.wms.inventory.model.Inventory.InventoryTransactCriteria;
import com.deer.wms.inventory.model.Inventory.InventoryTransactDto;
import com.deer.wms.inventory.service.InventoryService;
import com.deer.wms.inventory.service.InventoryTransactService;
import com.deer.wms.project.root.core.result.CommonCode;
import com.deer.wms.project.root.exception.ServiceException;
import com.deer.wms.project.root.util.DateUtils;
import com.deer.wms.project.root.util.StringUtil;
import com.deer.wms.project.root.util.StringUtils;
import com.deer.wms.system.manage.model.organization.Organization;
import com.deer.wms.system.manage.service.CodeRuleService;
import com.deer.wms.system.manage.service.OrganizationService;
import com.google.common.base.Preconditions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Created by 郭靖勋 on 2019/12/18.
 */
@Service
@Transactional
public class InventoryTransactServiceImpl extends ServiceImpl<InventoryTransactMapper, InventoryTransact> implements InventoryTransactService {

    @Autowired
    private InventoryTransactMapper inventoryTransactMapper;
    @Autowired
    private InventoryService inventoryService;
    @Autowired
    private InventoryMapper inventoryMapper;
    @Autowired
    private OrganizationService organizationService;
    @Autowired
    private CellInfoService cellInfoService;
    @Autowired
    private CodeRuleService codeRuleService;

    @Override
    public List<InventoryTransactDto> findList(InventoryTransactCriteria criteria) {
        return inventoryTransactMapper.findList(criteria);
    }

    @Override
    public int run(InventoryTransact inventoryTransact) {
        Integer transactType = inventoryTransact.getTransactType();

        //TYPE: 收货
        if (transactType.equals(InventoryConstant.TRANSACT_TYPE_ACCEPT)
                || transactType.equals(InventoryConstant.TRANSACT_TYPE_BLIND) ||
                transactType.equals(InventoryConstant.TRANSACT_TYPE_ASN)) {
            Inventory inventory = handleInStore(inventoryTransact);
            return inventory.getInventoryId();
        }

        //TYPE: 拆分
        if (InventoryConstant.TRANSACT_TYPE_PACK.equals(transactType)) {
            Inventory inventory = handlePack(inventoryTransact);
            return inventory.getInventoryId();
        }

        //TYPE:  转移 / 上架
        if (InventoryConstant.TRANSACT_TYPE_UP.equals(transactType) || InventoryConstant.TRANSACT_TYPE_MOVE.equals(transactType)) {
            Inventory inventory = handleInnerTransfer(inventoryTransact);
            return inventory.getInventoryId();
        }

        //TYPE: 拣货
        if (InventoryConstant.TRANSACT_TYPE_PICK.equals(transactType)) {
            Inventory inventory = handlePick(inventoryTransact);
            return inventory.getInventoryId();
        }

        //TYPE: 出库 不需要这一块逻辑
        if (InventoryConstant.INVENTORY_TYPE_OUT.equals(transactType)) {
            Inventory inventory = handleOutStore(inventoryTransact);
            return inventory.getInventoryId();
        }

        //TYPE: 库存调整
        if (transactType.equals(InventoryConstant.INVENTORY_ADJUST)) {
            Inventory inventory = handleAdjust(inventoryTransact);
            return inventory.getInventoryId();
        }

        //TYPE: 解冻
        if (transactType.equals(InventoryConstant.INVENTORY_UNFREEZE) || transactType.equals(InventoryConstant.INVENTORY_FREEZE)) {
            //按照条件找到所有的库存信息
//            QueryWrapper<Inventory> qw = Wrappers.query();
//            Map<String, Object> map = new HashMap<>(3);
            //根据物料批次找到所有对应的库存
//            map.put("ware_id", inventoryTransact.getWareId());
//            map.put("item_code", inventoryTransact.getItemCode());
//            map.put("batch_name", inventoryTransact.getFromBatchName());
//            List<Inventory> inventories = inventoryMapper.selectList(qw.allEq(map, true));

            Inventory inventory = inventoryService.getById(inventoryTransact.getFromInventoryId());
//            for (Inventory inventory : inventories) {
                if (transactType.equals(InventoryConstant.INVENTORY_UNFREEZE)) {
                    inventory.setState(InventoryConstant.TRANSACT_STATE_NORMAL);
                    inventory.setFreezeQuantity(0.0);
                    inventory.setStateDis(null);
                } else {
                    inventory.setFreezeQuantity(inventoryTransact.getFromQuantity());
//                    inventory.setState(InventoryConstant.TRANSACT_STATE_UNNORMAL);
                    inventory.setStateDis(inventoryTransact.getStateDis());
                }

//            }
            inventoryService.updateById(inventory);
        }
        return 0;
    }

    /**
     * 上架  转移  都是整个转移
     * @param inventoryTransact 库存事务
     * @return Inventory
     */
    private Inventory handleInnerTransfer(InventoryTransact inventoryTransact) {
        //来源库存
        Inventory fromInventory = inventoryService.getById(inventoryTransact.getFromInventoryId());

        //只需要修改库位即可
        if (ObjectUtil.isNotNull(fromInventory)) {
            fromInventory.setCellCode(inventoryTransact.getToCellCode());
            inventoryService.updateById(fromInventory);
        } else {
            throw new ServiceException(CommonCode.SERVER_INERNAL_ERROR, "未找到对应库存");
        }
        return fromInventory;
    }

    /**
     * 分拣类型事务提交
     *
     * @param inventoryTransact 事务
     * @return Inventory
     */
    private Inventory handlePick(InventoryTransact inventoryTransact) {
        Inventory fromInventory = inventoryService.getById(inventoryTransact.getFromInventoryId());
        Inventory toInventory;
        //只需要修改库位即可
        if (ObjectUtil.isNotNull(fromInventory)) {
            //数量不等，则需要分拣
            if (fromInventory.getQuantity().equals(inventoryTransact.getToQuantity())) {
                fromInventory.setCellCode(inventoryTransact.getToCellCode());
                fromInventory.setAllotQuantity(0.0);
                toInventory = fromInventory;
            } else {
                //存在分配数量小于实际拣货数量的情况，超发场景
                if (fromInventory.getAllotQuantity() >= inventoryTransact.getToQuantity()) {
                    fromInventory.setAllotQuantity(fromInventory.getAllotQuantity() - inventoryTransact.getToQuantity());
                } else {
                    fromInventory.setAllotQuantity(0.0);
                }

                fromInventory.setQuantity(fromInventory.getQuantity() - inventoryTransact.getToQuantity());
                toInventory =  processInventoryData(inventoryTransact);
                inventoryService.save(toInventory);
            }
            inventoryService.updateById(fromInventory);
        } else {
            throw new ServiceException(CommonCode.SERVER_INERNAL_ERROR, "未找到对应库存");
        }
        return toInventory;
    }

    /**
     * 出库类型事务提交
     *
     * @param inventoryTransact 事务
     * @return Inventory
     */
    private Inventory handleOutStore(InventoryTransact inventoryTransact) {
        Integer wareId = inventoryTransact.getWareId();
        String cellCode = inventoryTransact.getFromCellCode();
        String boxCode = inventoryTransact.getFromBoxCode();
        Integer packDetailId = inventoryTransact.getFromPackDetailId();
        Double transRatio = inventoryTransact.getFromTransRatio();
        String itemCode = inventoryTransact.getItemCode();
        Integer batchId = inventoryTransact.getFromBatchId();
        Inventory inventory = null;
        if (batchId == null) {
            String batchName = inventoryTransact.getFromBatchName();
            inventory = inventoryService.getSameInventoryNew(wareId, cellCode, boxCode, packDetailId, itemCode, batchName, transRatio);
        } else {
            inventory = inventoryService.getSameInventory(wareId, cellCode, boxCode, packDetailId, itemCode, batchId, transRatio);
        }
        inventory.setQuantity(inventory.getQuantity() - inventoryTransact.getFromQuantity());
        inventory.setAllotQuantity(inventory.getAllotQuantity() - inventoryTransact.getFromQuantity());
        if(inventory.getAllotQuantity()<0){
            inventory.setAllotQuantity(0.0);
        }
        inventoryService.updateById(inventory);
        //库存为0 直接删除库存
        if (inventory.getQuantity() == 0) {
            inventoryService.removeById(inventory.getInventoryId());
        }
        return inventory;
    }

    private Inventory handleAdjust(InventoryTransact inventoryTransact) {
        Inventory inventory = inventoryService.getById(inventoryTransact.getFromInventoryId());
        inventory.setQuantity(inventoryTransact.getToQuantity());
        inventoryService.updateById(inventory);

        //库存为0 直接删除库存
        if (inventory.getQuantity() == 0) {
            inventoryService.removeById(inventory.getInventoryId());
        }
        return inventory;
    }

    /**
     * 转移类型事务提交<p>
     * 有三种，没有任何区别
     * 1)上架;
     * 2)整箱转移;
     * 3)整箱拣货;
     *
     * @param inventoryTransact 库存事务
     * @return Inventory
     */
    private Inventory handleTransfer(InventoryTransact inventoryTransact) {
        //来源库存
        Inventory fromInventory = inventoryService.getSameInventory(
                inventoryTransact.getWareId(),
                inventoryTransact.getFromCellCode(), //来源库位
                inventoryTransact.getFromBoxCode(), //来源容器
                inventoryTransact.getFromPackDetailId(),
                inventoryTransact.getItemCode(),
                inventoryTransact.getFromBatchId(),
                inventoryTransact.getToTransRatio());
        //只需要修改库位即可
        if (ObjectUtil.isNotNull(fromInventory)) {
            Integer integer = cellInfoService.findbyCellCode(inventoryTransact.getToCellCode());
            //todo erp导入过来有库存id,手动入库需要统一
            if (ObjectUtil.isNotEmpty(integer)) {
                fromInventory.setErpAreaId(integer);
            }
            fromInventory.setCellCode(inventoryTransact.getToCellCode());
            fromInventory.setTransRatio(1.0);
            inventoryService.updateById(fromInventory);
        } else {
            throw new ServiceException(CommonCode.SERVER_INERNAL_ERROR, "未找到对应库存");
        }

        //目的库存
//        Inventory toInventory = inventoryService.getSameInventory(
//                inventoryTransact.getWareId(),
//                inventoryTransact.getToCellCode(), //目标库位
//                inventoryTransact.getFromBoxCode(),//来源容器
//                inventoryTransact.getToPackDetailId(),
//                inventoryTransact.getItemCode(),
//                inventoryTransact.getToBatchId(),
//                inventoryTransact.getToTransRatio());
//        if (toInventory == null) {
//            toInventory = processInventoryData(inventoryTransact);
//            toInventory.setPackDescribe(fromInventory.getPackDescribe());
//            inventoryService.save(toInventory);
//        } else {
//            toInventory.setQuantity(toInventory.getQuantity() + inventoryTransact.getToQuantity());
//            inventoryService.updateById(toInventory);
//        }
//        if (true) {throw new ServiceException(CommonCode.SERVER_INERNAL_ERROR);}
        return fromInventory;
    }

    /**
     * 组托类型事务提交<p>
     * 库存拆分 库位库存转移到容器库存 [库位库存扣减,容器库存新增]
     *
     * @param inventoryTransact 库存事务
     * @return Inventory
     */
    private Inventory handlePack(InventoryTransact inventoryTransact) {
        //找到库位库存
        Inventory fromInv = inventoryService.getById(inventoryTransact.getFromInventoryId());
        //扣减数量
        fromInv.setQuantity(fromInv.getQuantity() - inventoryTransact.getToQuantity());
        //当合格数量跟冻结数量都为0时删除库存
        if (fromInv.getQuantity().equals(0.0) && fromInv.getFreezeQuantity().equals(0.0)) {
            inventoryService.removeById(fromInv.getInventoryId());
        } else {
            inventoryService.updateById(fromInv);
        }

        //容器库存
        Inventory toInv = processInventoryData(inventoryTransact);
        inventoryService.save(toInv);
        return toInv;
    }

    /**
     * 入库类型事务提交<p>
     * 1)直接入库到库位
     * 2)直接入库到容器
     *
     * @param inventoryTransact 库存事务
     * @return 库存
     */
    private Inventory handleInStore(InventoryTransact inventoryTransact) {
        Inventory inventory = new Inventory();
        //事务类型
        inventory.setWareId(inventoryTransact.getWareId());
        inventory.setWareName(inventoryTransact.getWareName());
        //货主
        if (ObjectUtil.isNull(inventoryTransact.getToOrganizationId())) {
            //获取本仓库
            Organization sys_mine = organizationService.getOneByField("organization_code", "SYS_MINE");
            inventory.setOrganizationId(sys_mine.getOrganizationId());
            inventory.setOrganizationName(sys_mine.getOrganizationName());
        } else {
            inventory.setOrganizationId(inventoryTransact.getToOrganizationId());
            inventory.setOrganizationName(inventoryTransact.getToOrganizationName());
        }
        //库位
        inventory.setCellCode(inventoryTransact.getToCellCode());
        //箱号
        inventory.setBoxCode(inventoryTransact.getToBoxCode());
        //物料
        inventory.setItemCode(inventoryTransact.getItemCode());
        inventory.setItemName(inventoryTransact.getItemName());
        inventory.setSpec(inventoryTransact.getSpec());
        inventory.setModel(inventoryTransact.getModel());
        //批次
        inventory.setBatchId(inventoryTransact.getToBatchId());
        inventory.setBatchName(inventoryTransact.getToBatchName());
        //计量单位
        Integer toPackDetailId = inventoryTransact.getToPackDetailId();
        String toPackDescribe = inventoryTransact.getToPackDescribe();
        Double toTransRatio = inventoryTransact.getToTransRatio() == null ? 1.00 : inventoryTransact.getToTransRatio();
        inventory.setPackDetailId(toPackDetailId);
        inventory.setPackDescribe(toPackDescribe);
        inventory.setTransRatio(toTransRatio);

        //状态 0-冻结 1-正常
        inventory.setState(inventoryTransact.getState());
        if (ObjectUtil.isNotNull(inventoryTransact.getState()) && InventoryConstant.TRANSACT_STATE_UNNORMAL.equals(inventoryTransact.getState())) {
            inventory.setFreezeQuantity(inventoryTransact.getToQuantity());
            inventory.setQuantity(0.0);
            inventory.setStateDis(inventoryTransact.getStateDis());
        } else {
            inventory.setQuantity(inventoryTransact.getToQuantity());
            inventory.setFreezeQuantity(0.0);
        }
        //有效期,收货时间,库存事务创建时间
        inventory.setAcceptTime(inventoryTransact.getCreateTime());
        inventoryService.save(inventory);
        return inventory;
    }

    /**
     * 整理库存数据
     *
     * @param inventoryTransact 库存事务
     */
    private Inventory processInventoryData(InventoryTransact inventoryTransact) {
        Inventory inventory = new Inventory();
        //仓库
        Integer fromWareId = inventoryTransact.getWareId();
        String fromWareName = inventoryTransact.getWareName();
        //TODO:调拨可能单独处理
//        Integer toWareId = inventoryTransact.getToWareId();
//        String toWareName = inventoryTransact.getToWareName();
        inventory.setWareId(fromWareId);
        inventory.setWareName(fromWareName);
        //货主
        if (ObjectUtil.isNull(inventoryTransact.getToOrganizationId())) {
            //获取本仓库
            Organization sys_mine = organizationService.getOneByField("organization_code", "SYS_MINE");
            inventory.setOrganizationId(sys_mine.getOrganizationId());
            inventory.setOrganizationName(sys_mine.getOrganizationName());
        } else {
            inventory.setOrganizationId(inventoryTransact.getToOrganizationId());
            inventory.setOrganizationName(inventoryTransact.getToOrganizationName());
        }

        //库位
        String fromCellCode = inventoryTransact.getFromCellCode();
        String toCellCode = inventoryTransact.getToCellCode();
        inventory.setCellCode(toCellCode);

        //箱号
        String fromBoxCode = inventoryTransact.getFromBoxCode();
        String toBoxCode = inventoryTransact.getToBoxCode();
        //收存
        inventory.setBoxCode(toBoxCode);

        //物料
        inventory.setItemCode(inventoryTransact.getItemCode());
        inventory.setItemName(inventoryTransact.getItemName());
        inventory.setSpec(inventoryTransact.getSpec());
        inventory.setModel(inventoryTransact.getModel());
        inventory.setImgUrl(inventoryTransact.getImgUrl());
        //批次
//        Integer fromBatchId = inventoryTransact.getFromBatchId();
//        String fromBatchName = inventoryTransact.getFromBatchName();  批次应该只有一种情况
        Integer toBatchId = inventoryTransact.getToBatchId();
        String toBatchName = inventoryTransact.getToBatchName();
        inventory.setBatchId(toBatchId);
        inventory.setBatchName(toBatchName);

        //数量
        Double fromQuantity = inventoryTransact.getFromQuantity();
        Double toQuantity = inventoryTransact.getToQuantity();
        inventory.setQuantity(toQuantity);

        //计量单位
        Integer fromPackDetailId = inventoryTransact.getFromPackDetailId();
        String fromPackDescribe = inventoryTransact.getFromPackDescribe();
        Double fromTransRatio = inventoryTransact.getFromTransRatio();
        Integer toPackDetailId = inventoryTransact.getToPackDetailId();
        String toPackDescribe = inventoryTransact.getToPackDescribe();
        Double toTransRatio = inventoryTransact.getToTransRatio() == null ? 1.00 : inventoryTransact.getToTransRatio();
        inventory.setPackDetailId(toPackDetailId);
        inventory.setPackDescribe(toPackDescribe);
        inventory.setTransRatio(toTransRatio);

        //状态 0-冻结 1-正常
        inventory.setState(inventoryTransact.getState());
        if (ObjectUtil.isNotNull(inventoryTransact.getState()) && InventoryConstant.TRANSACT_STATE_UNNORMAL.equals(inventoryTransact.getState())) {
            inventory.setFreezeQuantity(inventory.getQuantity());
        }
        inventory.setStateDis(inventoryTransact.getStateDis());
        //单据号
        inventory.setBillNo(inventoryTransact.getBillNo());
        //收货时间,拆分一个的时候前面会把原本库存删掉导致新库存无收货时间
        inventory.setAcceptTime(inventoryTransact.getCreateTime());
        return inventory;
    }

}
